package com.ss.android.auto.launch.tasks.collector

import android.util.Log
import com.ss.android.auto.extentions.castTo
import com.ss.android.auto.init.AppCoreData
import com.ss.android.auto.launch.TAG
import com.ss.android.auto.log.AutoLog

/**
 *  @author zhongxinyuan @ ByteDance Inc
 *  @since   2023/2/1
 */
abstract class MainThreadTaskCollector : TaskCollector() {

    // 需要等待执行完成的子线程
    private var dependCollectors: MutableSet<TaskCollector> = mutableSetOf()
    internal var rescheduledTasksCost = 0L

    override fun executeTasks(tasksWrapper: List<() -> Unit>) {
        markGroupStart()
        tasksWrapper.forEach { task ->
            task.invoke()
        }
        markGroupEnd()

        // 从同一阶段的子线程任务中找一个还没开始的拿出来执行
        val start = System.currentTimeMillis()
        dependCollectors.forEach {
            while (it.findOnePendingSubTask() != null) {
                it.findOnePendingSubTask()?.apply {
                    Log.d(
                            TAG,
                            "${this@MainThreadTaskCollector.javaClass.simpleName} findOnePendingSubTask,found! start run..."
                    )
                }?.invoke(true)?.apply {
                    Log.d(
                            TAG,
                            "${this@MainThreadTaskCollector.javaClass.simpleName} findOnePendingSubTask,found! run end"
                    )
                }
            }
        }
        rescheduledTasksCost = System.currentTimeMillis() - start

        // 确认同一阶段的子线程任务都完成了，如果没完成则 wait
        dependCollectors.forEach {
            val s = System.currentTimeMillis()
            it.castTo(AsyncThreadTaskCollector::class.java)?.waitComplete()?.apply {
                val cost = System.currentTimeMillis() - s
                if (cost > DANGER_WAIT_TIME && (AppCoreData.getInstance().isLocalTest || AppCoreData.getInstance().isUpdate)) {
                    it.statistic.getTasksFinishAfter(s).firstOrNull { t -> t.duration > DANGER_WAIT_TIME }?.run {
                        val msg = "${this@MainThreadTaskCollector.javaClass.simpleName} wait ${this.name} done. $cost"
                        AutoLog.ensureNotReachHere(msg)
                        Log.e(TAG, msg)
                    }
                }
            }
        }

    }

    fun waitForComplete(taskCollector: TaskCollector) {
        dependCollectors.add(taskCollector)
    }

    companion object {
        const val DANGER_WAIT_TIME = 200L
    }
}